#include "AP.h"

const char	AP_TIMESTAMP	=	0x1;
const char	AP_TEMPERATURE	=	0x2;
const char	AP_PATIENT_ID	=	0x3;
const char	AP_ACCELEROMETER=	28;
const char	AP_FS_ECG		=	0x0A;
const char	AP_ECG_LEAD		=	0x12;
const char	AP_5ADCCH		=	0x1B;
const char	AP_3ADCCH		=	0x04;
const char	AP_IMPEDANCE	=	0x14;
const char	AP_CO			=	0x2d;


const char AP_BEGIN = 0x53;
const char AP_END	= 0x50;


typedef struct FrameHeader
{
	char StartOfPacket;
	char NumberOfAttributes;
}FrameHeader;



AP::AP(wxWindow *pParent):APDialog(pParent)
{
	Instrument::Instrument();
	
	DigitalOffset = 2048;
	DigitalMax = 4096;
	DigitalMin = 0;
	Resolution = 1;
		
	MyName = _("AP");
	Recursion	= 0;
	Labels[0] = wxString::Format(wxT("ACCX"));
	Labels[1] = wxString::Format(wxT("ACCY"));
	Labels[2] = wxString::Format(wxT("ACCZ"));
	Labels[3] = wxString::Format(wxT("ECG1"));
	Labels[4] = wxString::Format(wxT("ECG2"));
	Labels[5] = wxString::Format(wxT("ECG3"));
	Labels[6] = wxString::Format(wxT("DZ"));
	Labels[7] = wxString::Format(wxT("Z0"));
	Show();
	Initialize(8,250,20);
	pDev = NULL;
}

AP::~AP(void)
{
	if(pDev != NULL)
	{
		delete pDev;
		pDev = NULL;
	}
}

void AP::GetAttribute(Attribute *pAttr)
{
	int Read;
	/*while(pDev->Read((char*)pAttr,3)==0)
	{
		Sleep(1);
	}*/
	pDev->Read((char*)pAttr,3);
	if(pAttr->Length!=0)
	{
		Read = pDev->Read(&pAttr->Parameters[0],pAttr->Length);
	}
}


int AP::GetFrame(Attribute *pAttr)
{
	char	End;
	Recursion++;
	FrameHeader	Head;

	do{
		Sleep(1);
		pDev->Read(&Head.StartOfPacket,1);
	}while(Head.StartOfPacket != AP_BEGIN && !Esci);

	while(pDev->Read(&Head.NumberOfAttributes,1)==0 && !Esci);

	for(int i=0; i<Head.NumberOfAttributes;i++)
	{
		GetAttribute(&pAttr[i]);
	}
	pDev->Read(&End,1);
	if(End == AP_END)
	{
		Recursion = 0;
		return Head.NumberOfAttributes;
	}else
	{
		IncErrorCounter();
		do{
			pDev->Read(&End,1);
		}while(End != AP_END && !Esci);
		if(Recursion < 10)
		{
			Head.NumberOfAttributes = GetFrame(pAttr);
			return (Head.NumberOfAttributes==0)?0:Head.NumberOfAttributes;
		}else
		{
			return -1;
		}
	}
}

int Max(int x, int y, int z)
{
	if(x >=y && x>=z) return x;
	if(y >=x && y>=z) return y;
	return z;
}
int Min(int x, int y, int z)
{
	if(x <=y && x<=z) return x;
	if(y <=x && y<=z) return y;
	return z;
}

#define TYPICAL_ECG_LEN	500
#define MAX_SAMPLES		100

void* AP::Entry(void)
{
	bool		RapportiDiForzaCalcolati;
	signed short int	*pInt;
	unsigned short *pT;
	Attribute	Attrs[TYPICAL_ECG_LEN];
	int Len,u,i,AttrsInFrame,z;
	bool Complete;
	SampleStruct	Signal[MAX_SAMPLES];

	signed short int TTTT;
	int IACC,IECG,ICO;
	int CACC,CECG,CCO;

	Esci = false;
	RapportiDiForzaCalcolati = false;
	IACC = IECG = ICO = 0;
	memset(&Signal,0,sizeof(Signal));
	for(i=0;i<MAX_SAMPLES;i++)	Signal[i].Data.DataLen	=	Channels;						
	while(!Esci)
	{
		if(IsRunning)
		{
			Len = 0;
			Complete = false;
			//	do{
			for(u=0;u<3;u++)
			{
				AttrsInFrame = GetFrame(&Attrs[Len]);
				Len+=AttrsInFrame;
			}

			//Len = AttrsInFrame;
			if(Len <= 0) 
			{
				IncErrorCounter();
			}
			if(!RapportiDiForzaCalcolati)
			{
				CACC = CECG = CCO = 0;
				for(i=0;i<Len;i++)
				{
					switch(Attrs[i].ID)
					{
					case AP_ACCELEROMETER:
						CACC = Attrs[i].Length/6;
						break;
					case AP_3ADCCH:
						CECG = Attrs[i].Length/6;
						break;
					case AP_CO:
						CCO = Attrs[i].Length/4;
						break;
					}
				}

					int MAX = Max(CECG,CACC,CCO);
					if(CECG != 0) CECG = MAX/CECG;
					if(CACC != 0) CACC = MAX/CACC;
					if(CCO != 0) CCO = MAX/CCO;
					RapportiDiForzaCalcolati = true;
				
			}
			for(i=0;i<Len;i++)
			{
				switch(Attrs[i].ID)
				{
				case AP_TIMESTAMP:
					unsigned int Stamp;
					memcpy(&Stamp,Attrs[i].Parameters,sizeof(unsigned int));
					Signal[0].Events.CommunicationStats = Stamp;
					break;
				case AP_ACCELEROMETER:
					pInt = (short int*)Attrs[i].Parameters;
					for(int t=0;t<Attrs[i].Length/6;t++)
					{
						for(z =0;z<CACC;z++)
						{
							TTTT = pInt[0];
							Signal[IACC].Data.Signal[0]=2048+TTTT/16;
							TTTT = pInt[1];
							Signal[IACC].Data.Signal[1]=2048+TTTT/16;
							TTTT = pInt[2];
							Signal[IACC].Data.Signal[2]=2048+TTTT/16;
							IACC++;
							if(IACC > MAX_SAMPLES)
							{
								IACC = 0;
							}
						}
						pInt+=3;
					}
					break;
				case AP_3ADCCH:
					pT = (unsigned short*)Attrs[i].Parameters;
					for(int t=0;t<Attrs[i].Length/6;t++)
					{
						for(z =0;z<CECG;z++)
						{

							Signal[IECG].Data.Signal[3]=pT[0];
							Signal[IECG].Data.Signal[4]=pT[1];
							Signal[IECG].Data.Signal[5]=pT[2];
							//	Signal[IECG].Data.Signal[6]=*pT++;
							//	Signal[IECG].Data.Signal[7]=*pT++;
							IECG++;
							if(IECG > MAX_SAMPLES)
							{
								IECG = 0;
							}
						}
						pT+=3;
					}
					break;
				case AP_CO:
					pT = (unsigned short*)Attrs[i].Parameters;
					for(int t=0;t<Attrs[i].Length/4;t++)
					{
						for(z =0;z<CCO;z++)
						{
							Signal[ICO].Data.Signal[6]=pT[0];
							Signal[ICO].Data.Signal[7]=pT[1];
							ICO++;
							if(ICO > MAX_SAMPLES)
							{
								ICO = 0;
							}
						}
						pT+=2;
					}
					break;
				default:
					break;
				}

			}
			if(!Esci)
			{
				Len = Min(IECG,IACC,ICO);
				if(Len > 0)
				{
					IECG -= Len;
					IACC -= Len;
					ICO -= Len;

					for(u = 0;u<Len;u++)
					{
						PutSample(&Signal[u]);
					}
				}
				memmove(&Signal[0],&Signal[Len],sizeof(HimDataStruct)*(MAX_SAMPLES-Len));
			}
		}
		else Sleep(100);

	}

	StopDevice();
	Sleep(1000);
	pDev->Close();

	return NULL;
}
/*
void* AP::Entry(void)
{
	short int	*pInt;
	unsigned short *pT;
	Attribute	Attrs[TYPICAL_ECG_LEN];
	int Len,u,i,AttrsInFrame,z;
	bool Complete;
	SampleStruct	Signal[50];
	

	int IACC,IECG,ICO;
	int CACC,CECG,CCO;

	Esci = false;
	while(!Esci)
	{
		if(IsRunning)
		{
			memset(&Signal,0,sizeof(Signal));
			for(i=0;i<50;i++)	Signal[i].Data.DataLen	=	Channels;
			Len = 0;
			Complete = false;
		//	do{
			for(int u=0;u<3;u++)
			{
				AttrsInFrame = GetFrame(&Attrs[Len]);
				Len+=AttrsInFrame;
			}
			
			//Len = AttrsInFrame;
			if(Len <= 0) 
			{
				IncErrorCounter();
			}
			
			IACC = IECG = ICO = 0;
			CACC = CECG = CCO = 0;
			for(i=0;i<Len;i++)
			{
				switch(Attrs[i].ID)
				{
				case AP_ACCELEROMETER:
					CACC = Attrs[i].Length/6;
					break;
				case AP_3ADCCH:
					CECG = Attrs[i].Length/6;
					break;
				case AP_CO:
					CCO = Attrs[i].Length/4;
					break;
				}
			}
			int MAX = Max(CECG,CACC,CCO);
			if(CECG != 0) CECG = MAX/CECG;
			if(CACC != 0) CACC = MAX/CACC;
			if(CCO != 0) CCO = MAX/CCO;
			for(i=0;i<Len;i++)
			{
				switch(Attrs[i].ID)
				{
				case AP_TIMESTAMP:
					unsigned int Stamp;
					memcpy(&Stamp,Attrs[i].Parameters,sizeof(unsigned int));
					Signal[0].Events.CommunicationStats = Stamp;
					break;
				case AP_ACCELEROMETER:
					pT = (unsigned short *)Attrs[i].Parameters;
					for(int t=0;t<Attrs[i].Length/6;t++)
					{
						for(z =0;z<CACC;z++)
						{
						
							Signal[IACC].Data.Signal[0]=pT[0];
							Signal[IACC].Data.Signal[1]=pT[1];
							Signal[IACC].Data.Signal[2]=pT[2];
							IACC++;
							if(IACC > 50)
							{
								IACC = 0;
							}
						}
						pT+=3;
					}
					break;
				case AP_3ADCCH:
					pT = (unsigned short*)Attrs[i].Parameters;
					for(int t=0;t<Attrs[i].Length/6;t++)
					{
						for(z =0;z<CECG;z++)
						{
						
							Signal[IECG].Data.Signal[3]=pT[0];
							Signal[IECG].Data.Signal[4]=pT[1];
							Signal[IECG].Data.Signal[5]=pT[2];
					//	Signal[IECG].Data.Signal[6]=*pT++;
					//	Signal[IECG].Data.Signal[7]=*pT++;
							IECG++;
							if(IECG > 50)
							{
								IECG = 0;
							}
						}
						pT+=3;
					}
					break;
				case AP_CO:
					pT = (unsigned short*)Attrs[i].Parameters;
					for(int t=0;t<Attrs[i].Length/4;t++)
					{
						for(z =0;z<CCO;z++)
						{
							Signal[ICO].Data.Signal[6]=pT[0];
							Signal[ICO].Data.Signal[7]=pT[1];
							ICO++;
						}
						pT+=2;
					}
					break;
					default:
					break;
				}

			}
			if(!Esci)
			{
				Len = Max(IECG,IACC,0);
				for(u = 0;u<Len;u++)
				{
					PutSample(&Signal[u]);
				}
			}
		}
		else Sleep(100);

	}

	StopDevice();
	Sleep(1000);
	pDev->Close();
	
	return NULL;
}*/
void AP::StartDevice(wxString FileName,wxString FilePath,bool File)
{
	char TestMode[]={(char)0x53,(char)0x01,(char)0x8f,(char)0x01,(char)0x01,(char)0x01,(char)0x50};
	Instrument::StartDevice(FileName,FilePath,File);
	char ch = 's';
	if(!IsRunning)
	{
		
		if(pDev !=NULL)
		{
			pDev->Write(TestMode,sizeof(TestMode));
			IsRunning	=	true;
		}
	}
}
void AP::StopDevice(void)
{
	char Stop[]={(char)0x53,(char)0x01,(char)0x8f,(char)0x01,(char)0x01,(char)0x00,(char)0x50};
	//char ch = 't';
	if(IsRunning)
	{
		IsRunning	=	false;
		if(pDev !=NULL)		pDev->Write(Stop,sizeof(Stop));
	//	if(pDev !=NULL)		pDev->Write(&ch,sizeof(char));
		Instrument::StopDevice();
	}
}
int AP::OpenPort(const char *PortName, const char *OpenVal2, const char *OpenVal3)
{
	wxBaud baudrate = wxBAUD_115200;

	if(pDev == NULL)	pDev = new wxSerialPort();
	if(pDev->Open(PortName) < 0)
	{
		return -1;	
	}
	pDev->SetBaudRate(baudrate);
	return 1;
}